package vip.xiaonuo.modular.manage.storeorder.service.impl;

import cc.blynk.clickhouse.ClickHouseConnection;
import cc.blynk.clickhouse.ClickHouseDataSource;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import vip.xiaonuo.core.factory.PageFactory;
import vip.xiaonuo.core.pojo.page.PageResult;
import vip.xiaonuo.dbs.core.annotation.DataSource;
import vip.xiaonuo.modular.common.LoadClickhouseDatasource;
import vip.xiaonuo.modular.common.WdAnalysisConst;
import vip.xiaonuo.modular.manage.bioperateddata.entity.BiOperatedData;
import vip.xiaonuo.modular.manage.bioperateddata.service.BiOperatedDataService;
import vip.xiaonuo.modular.manage.storeorder.entity.BiStoreOrder;
import vip.xiaonuo.modular.manage.storeorder.mapper.BiStoreOrderMapper;
import vip.xiaonuo.modular.manage.storeorder.param.BiStoreOrderParam;
import vip.xiaonuo.modular.manage.storeorder.service.BiStoreOrderService;

import javax.annotation.Resource;
import java.io.*;
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

@Slf4j
@Service
public class BiStoreOrderServiceImpl extends ServiceImpl<BiStoreOrderMapper, BiStoreOrder> implements BiStoreOrderService {

    @Resource
    private BiOperatedDataService biOperatedDataService;

    @Override
    public void upload(MultipartFile file) throws IOException {
        InputStream inputStream = file.getInputStream();

//        Reader in = new FileReader("Z:\\新建文件夹\\茶百道数据\\茶百道湖北地区订单\\202201-1.csv");
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream,"UTF-8");
        Reader in = new BufferedReader(inputStreamReader);
//        csv解析文件

        String [] headers = {"业务经理","代理商","业务员","商户名称","商户号","门店名"
                ,"支付类型","银行卡类型","创建时间","终端号","终端流水号","终端交易时间","订单号","退款单号"
                ,"官方订单号","交易金额（元）","退款金额（元）","手续费金额（元）","结余金额（元）","支付状态","交易状态说明"
                ,"退款状态说明","支付方式","订单描述","通道类型","结算处理时间","退款完成时间","业务员分润（分）"
                ,"代理商分润（分）","业务经理分润（分）","用户id"
        };
        HashMap<String, BiOperatedData> storeInfoMap = new HashMap<>();

//        CSVParser parse = CSVFormat.EXCEL.parse(in);
        CSVParser parse = CSVFormat.DEFAULT.withHeader(headers).parse(in);
        List<BiStoreOrder> list = new ArrayList<>();
        for (CSVRecord records : parse) {
            String storeCode = StringUtils.trim(records.get("商户号"));
            BiStoreOrder biStoreOrder = new BiStoreOrder();
            biStoreOrder.setStoreName(records.get("门店名"));
            biStoreOrder.setPaidWay(records.get("支付方式"));

            String TradeAmount = records.get("交易金额（元）");
            String RefundAmount = records.get("退款金额（元）");
            if(NumberUtil.isNumber(TradeAmount)) {
                biStoreOrder.setTradeAmount(new BigDecimal(TradeAmount));
            }else{
                biStoreOrder.setTradeAmount(BigDecimal.ZERO);
            }
            if(NumberUtil.isNumber(RefundAmount)) {
                biStoreOrder.setRefundAmount(new BigDecimal(RefundAmount));
            }else{
                biStoreOrder.setRefundAmount(BigDecimal.ZERO);
            }
            biStoreOrder.setStoreCode(storeCode);
            Date createDate = null;
            try {
                createDate = DateUtil.parse(records.get("创建时间"));
            } catch (Exception e) {
                createDate = DateUtil.date();
            }
            biStoreOrder.setCreateDate(createDate);

            BiOperatedData info = null;
            if (storeInfoMap.containsKey(storeCode)) {
                info = storeInfoMap.get(storeCode);
            }else{
                LambdaQueryWrapper<BiOperatedData> wrapper = new LambdaQueryWrapper();
                wrapper.eq(BiOperatedData::getStoreId,storeCode);
                wrapper.last(" limit 1 ");
                info = biOperatedDataService.getOne(wrapper);
                storeInfoMap.put(storeCode, info);
            }
            if (info != null){
                biStoreOrder.setProvName(info.getProvName());
                biStoreOrder.setCityName(info.getCityName());
                biStoreOrder.setCountryName(info.getCountryName());
            }

            if (records.getRecordNumber() == 1L){
                continue;
            }
            list.add(biStoreOrder);
        }
        ClickHouseConnection connection = null;
        try {
            ClickHouseDataSource clickHouseDataSource = LoadClickhouseDatasource.get();
            connection = clickHouseDataSource.getConnection();
            connection.setAutoCommit(false);
            ClickHouseConnection finalConnection = connection;
            this.addClickHouse(list, finalConnection);
            System.out.println("解析完成！！！！！！！");
        } catch (Exception e) {
            log.error(list.get(0) + " >>> 添加失败", e);
        } finally {
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException ignore) {
                }
            }
        }
        parse.close();
        in.close();
    }

    @Override
    @DataSource(name = WdAnalysisConst.CLICKHOUSE_DATASOURCE)
    public PageResult<BiStoreOrder> storeDataListCHPage(BiStoreOrderParam biStoreOrderParam) {

        return new PageResult<>(this.baseMapper.pageStoreOrderData(PageFactory.defaultPage() , biStoreOrderParam));
    }

    final String insertSql = "insert into bi_store_order" +
            "" +
            "values (?, ?, ? , ? , ? , ? , ? , ? , ?)";


    public void addClickHouse(List<BiStoreOrder> list , ClickHouseConnection connection) {
        // 注意这里使用的CK自己实现的PreparedStatement
        PreparedStatement preparedStatement = null;
        try {
            preparedStatement = connection.prepareStatement(insertSql);
            for (BiStoreOrder biStoreOrder : list) {
                preparedStatement.setString(1, biStoreOrder.getStoreCode());
                preparedStatement.setString(2, biStoreOrder.getStoreName());
                preparedStatement.setBigDecimal(3, biStoreOrder.getTradeAmount());
                preparedStatement.setBigDecimal(4, biStoreOrder.getRefundAmount());
                preparedStatement.setString(5, biStoreOrder.getPaidWay());
                preparedStatement.setDate(6, new java.sql.Date(biStoreOrder.getCreateDate().getTime()));
                preparedStatement.setString(7, biStoreOrder.getProvName());
                preparedStatement.setString(8, biStoreOrder.getCityName());
                preparedStatement.setString(9 , biStoreOrder.getCountryName());
                preparedStatement.addBatch();
            }
            preparedStatement.executeBatch();
            connection.commit();
        } catch (SQLException e) {
            log.error(list.get(0).getStoreName() + ">>>写入数据库失败", e);
        } finally {
            if (preparedStatement != null) {
                try {
                    preparedStatement.close();
                } catch (SQLException ignore) {
                }
            }
        }
    }
}
